<template>
  <div class="file-upload-page">
    <!-- 页面标题 -->
    <h2 class="page-title">课件上传与预览</h2>

    <!-- 左右布局容器 -->
    <div class="layout-container">
      <!-- 左侧上传区域 -->
      <div class="upload-container">
        <div class="upload-card">
          <h3>上传文件</h3>

          <!-- 上传按钮 -->
          <label class="upload-btn">
            <input
              type="file"
              ref="fileInput"
              @change="handleFileChange"
              accept="image/*,.txt,.pdf,.doc,.docx,.xls,.xlsx,.ppt"
            >
            <i class="el-icon-upload"></i>
            <span>点击或拖拽文件到此处上传</span>
          </label>

          <!-- 上传限制说明 -->
          <div class="upload-info">
            <p>支持格式：图片、TXT、PDF、Word、Excel、PPT</p>
            <p>单个文件大小不超过 20MB</p>
          </div>

          <!-- 已上传文件列表 -->
          <div class="file-list" v-if="fileList.length > 0">
            <h4>已上传文件</h4>
            <div
              class="file-item"
              v-for="(file, index) in fileList"
              :key="index"
              @click="previewFile(index)"
            >
              <i
                :class="getFileIcon(file.type)"
                class="file-icon"
              ></i>
              <div class="file-info">
                <p class="file-name">{{ file.name }}</p>
                <p class="file-size">{{ formatFileSize(file.size) }}</p>
              </div>

            </div>
          </div>
        </div>
      </div>

      <!-- 右侧预览区域 -->
      <div class="preview-container">
        <div class="preview-card">
          <h3>文件预览</h3>

          <!-- 无预览时显示 -->
          <div class="empty-preview" v-if="!activeFile">
            <i class="el-icon-file-text"></i>
            <p>请选择一个文件进行预览</p>
            <p>word预览只支持.docx</p>
            <p>ppt预览只支持.pptx</p>
          </div>

          <!-- 图片预览 -->
          <div class="image-preview" v-if="activeFile && isImage(activeFile.type)">
            <img :src="activeFile.url" alt="预览图片" class="preview-img">
          </div>

          <!-- 文本文件预览 -->
          <div class="text-preview" v-if="activeFile && isText(activeFile.name)">
            <pre>{{ textContent }}</pre>
          </div>

          <!-- PDF预览 (使用iframe) -->
          <div class="pdf-preview" v-if="activeFile && isPdf(activeFile.name)">
            <iframe :src="activeFile.url" type="application/pdf" class="pdf-frame"></iframe>
          </div>

          <div class="preview-content" v-if="activeFile && isWord(activeFile.name)" v-html="htmlContent"></div>

<!--          <div class="preview-content" v-if="activeFile && isPPTX(activeFile.name)" v-html="picList"></div>-->
          <div id="pptContainer" ref="container" class="preview-content" v-if="activeFile && isPPTX(activeFile.name)"></div>

          <!-- 其他文件类型提示 -->
          <div class="other-preview" v-if="activeFile && !isSupported(activeFile.type, activeFile.name)">
            <i class="el-icon-info"></i>
            <p>不支持预览该类型文件</p>
            <p>文件名: {{ activeFile.name }}</p>
            <p>文件类型: {{ activeFile.type || '未知' }}</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import {getToken} from "@/utils/auth";
import {readWordAsArrayBuffer} from "@/utils/fileUtil";

// import PPTX2HTML from '@/utils/PPTX2HTML.js'
import JSZip from 'jszip'

export default {
  data() {
    return {
      fileList: [], // 已上传文件列表
      picList: [], // 已上传文件列表

      // 上传的地址
      url: process.env.VUE_APP_BASE_API + "/common/uploadNew",

      activeFile: null, // 当前预览文件
      textContent: '', // 文本文件内容
      htmlContent: ''

    }
  },
  methods: {
    // 处理文件上传
    handleFileChange(e) {
      const files = e.target.files
      // console.log(files[0])
      if (!files.length) return

      Array.from(files).forEach(file => {
        // 验证文件大小
        if (file.size > 20 * 1024 * 1024) {
          this.$message.error(`文件 ${file.name} 超过 20MB 限制`)
          return
        }

        // 创建文件预览URL
        const fileUrl = URL.createObjectURL(file)
        // console.log(fileUrl)

        // 添加到文件列表
        this.fileList.push({
          name: file.name,
          type: file.type,
          size: file.size,
          url: fileUrl,
          raw: file
        })
      })

      //上传到服务器
      // this.uploadServer(files[0])

      // 清空input值，允许重复上传同一文件
      this.$refs.fileInput.value = ''

      // 自动预览第一个文件
      if (this.fileList.length === 1) {
        this.previewFile(0)
      }
    },

    //上传到服务器
    uploadServer(file) {
      const formData = new FormData();
      formData.append('file', file);
      // console.log("FormData 中是否有文件：", formData.has("file"));

      axios.post(this.url, formData, {
        // 关键配置：允许携带 Cookie（需后端 AllowCredentials: true 配合）
        headers: {Authorization: "Bearer " + getToken()},
        withCredentials: true,
      }).then(res => {
        // console.log(res);
        // 3. 自定义成功处理（如关联业务数据）
        // this.bindFileToBusiness(res.data.fileId);
      }).catch(err => {
        console.error('上传失败', err);
      });

      // fetch(this.url, {
      //   headers: { Authorization: "Bearer " + getToken() },
      //   method: "POST",
      //   body: formData, // 直接传递 FormData，浏览器自动设置正确的 Content-Type
      //   credentials: "include" // 如需携带 Cookie
      // })
      //   .then(res => res.json())
      //   .then(data => {
      //     console.log(data)
      //   })
      //   .catch(err => console.error('失败', err));
    },

    // 预览文件
    async previewFile(index) {
      const file = this.fileList[index]
      this.activeFile = file

      // 处理文本文件内容
      if (this.isText(file.name)) {
        const reader = new FileReader()
        reader.onload = (e) => {
          this.textContent = e.target.result
        }
        reader.readAsText(file.raw)
      } else if (this.isWord(file.name)) {
        this.htmlContent = await readWordAsArrayBuffer(file.raw)
        // console.log(this.htmlContent)
      }
      else if (this.isPPTX(file.name)) {
        // this.picList = await readPPTXAsPic(file.raw)
        // let con = document.getElementById('pptContainer')
        // await readPPTXAsPicNew(file.raw, con)
        await this.handlePDF(file.raw)
        // console.log(this.picList)
      }
    },

    async handlePDF(file){
      const container = this.$refs.container
      container.innerHTML = '<p>正在解析 PPTX...</p>'
      try {
        // 读取文件为 ArrayBuffer
        const arrayBuffer = await file.arrayBuffer()
        const zip = new JSZip()
        const pptx = await zip.loadAsync(arrayBuffer)

        // 调用 pptx2html 转换
        const htmlStr = PPTX2HTML(pptx, {
          width: 960,
          height: 540,
          containerId: 'pptx-render-area'
        })

        // 渲染到页面
        container.innerHTML = `<div id="pptx-render-area">${htmlStr}</div>`
      } catch (error) {
        console.error('PPTX 解析失败:', error)
        container.innerHTML = '<p style="color: red;">解析失败，请检查文件格式。</p>'
      }
    },

    // 删除文件
    removeFile(index) {
      // 释放URL对象
      URL.revokeObjectURL(this.fileList[index].url)
      this.fileList.splice(index, 1)

      // 如果删除的是当前预览文件
      if (this.activeFile && this.activeFile.name === this.fileList[index]?.name) {
        this.activeFile = this.fileList[0] || null
        this.textContent = ''
      }
    },

    // 格式化文件大小
    formatFileSize(size) {
      if (size < 1024) return `${size} B`
      if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`
      return `${(size / (1024 * 1024)).toFixed(1)} MB`
    },

    // 获取文件图标
    getFileIcon(type) {
      if (this.isImage(type)) return 'el-icon-picture'
      if (type.includes('pdf')) return 'el-icon-file-pdf'
      if (type.includes('word')) return 'el-icon-file-word'
      if (type.includes('excel')) return 'el-icon-file-excel'
      if (this.isText(type)) return 'el-icon-file-text'
      return 'el-icon-file'
    },

    // 类型判断工具函数
    isImage(type) {
      return type.startsWith('image/')
    },

    isText(name) {
      return name.endsWith('.txt')
    },

    isPdf(name) {
      return name.endsWith('.pdf')
    },

    isWord(name) {
      return name.endsWith('.docx')
    },
    isPPTX(name) {
      return name.endsWith('.pptx')
    },

    isSupported(type, name) {
      return this.isImage(type) || this.isText(name) || this.isPdf(name) || this.isWord(name) || this.isPPTX(name)
    }
  },
  beforeDestroy() {
    // 清理URL对象，释放内存
    this.fileList.forEach(file => {
      URL.revokeObjectURL(file.url)
    })
  }
}
</script>

<style scoped>
.file-upload-page {
  padding: 20px;
  max-width: 1400px;
  margin: 0 auto;
}

.page-title {
  text-align: center;
  margin-bottom: 30px;
  color: #333;
}

.layout-container {
  display: flex;
  gap: 30px;
  height: calc(100vh - 120px);
}

/* 左侧上传区域 */
.upload-container {
  flex: 1;
}

.upload-card, .preview-card {
  height: 100%;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  padding: 20px;
  display: flex;
  flex-direction: column;
}

.upload-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 200px;
  border: 2px dashed #ddd;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s;
  margin-bottom: 20px;
  position: relative;
  overflow: hidden;
}

.upload-btn:hover {
  border-color: #409eff;
  background-color: #f5f7fa;
}

.upload-btn input {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}

.upload-btn i {
  font-size: 36px;
  color: #409eff;
  margin-bottom: 10px;
}

.upload-btn span {
  color: #666;
}

.upload-info {
  color: #999;
  font-size: 12px;
  margin-bottom: 20px;
  padding-left: 5px;
}

.upload-info p {
  margin: 5px 0;
}

.file-list {
  flex: 1;
  overflow-y: auto;
  margin-top: 10px;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 10px;
  border-radius: 4px;
  background-color: #f9f9f9;
  margin-bottom: 8px;
  cursor: pointer;
  transition: background-color 0.2s;
}

.file-item:hover {
  background-color: #f0f7ff;
}

.file-icon {
  font-size: 20px;
  margin-right: 12px;
  color: #409eff;
}

.file-info {
  flex: 1;
  overflow: hidden;
}

.file-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0;
  font-size: 14px;
}

.file-size {
  margin: 0;
  font-size: 12px;
  color: #999;
}

.delete-icon {
  color: #f56c6c;
  font-size: 16px;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 0.2s;
}

.delete-icon:hover {
  opacity: 1;
}

/* 右侧预览区域 */
.preview-container {
  flex: 1.5;
}

.empty-preview {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #999;
  border: 1px dashed #ddd;
  border-radius: 6px;
  margin-top: 10px;
}

.empty-preview i {
  font-size: 48px;
  margin-bottom: 15px;
}

.image-preview {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  margin-top: 10px;
  border: 1px dashed #ddd;
  border-radius: 6px;
  padding: 10px;
}

.preview-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.text-preview {
  flex: 1;
  margin-top: 10px;
  border: 1px dashed #ddd;
  border-radius: 6px;
  padding: 15px;
  overflow-y: auto;
  background-color: #f9f9f9;
}

.text-preview pre {
  white-space: pre-wrap;
  word-wrap: break-word;
  margin: 0;
  color: #333;
  font-family: monospace;
  font-size: 14px;
}

.pdf-preview {
  flex: 1;
  margin-top: 10px;
  border: 1px dashed #ddd;
  border-radius: 6px;
  overflow: hidden;
}

.pdf-frame {
  width: 100%;
  height: 100%;
  border: none;
}

.preview-container {
  padding: 10px;
  border: 1px solid #eee;
  border-radius: 4px;
  overflow-y: auto;
}

.preview-content {
  line-height: 1.8;
  font-size: 14px;
}

/* 优化预览样式（可选） */
::v-deep .preview-content p {
  margin: 10px 0;
}

::v-deep .preview-content img {
  max-width: 100%;
  margin: 10px 0;
}

::v-deep .preview-content table {
  border-collapse: collapse;
  margin: 10px 0;
}

::v-deep .preview-content table td,
::v-deep .preview-content table th {
  border: 1px solid #ccc;
  padding: 8px 12px;
}

.other-preview {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #666;
  border: 1px dashed #ddd;
  border-radius: 6px;
  margin-top: 10px;
  padding: 20px;
  text-align: center;
}

.other-preview i {
  font-size: 48px;
  margin-bottom: 15px;
  color: #999;
}

.other-preview p {
  margin: 5px 0;
}
</style>
